import netsvc
#import time

from osv import osv, fields
from osv.orm import intersect

class kdvn_payment_from_client(osv.osv):
    _name = 'kdvn.payment.from.client'
    _description="KDVN Payment From Client"
    
    def unlink(self, cr, uid, ids, context=None):
        if ids:
            payment_id = ",".join(map(str,ids))
            for rop in self.read(cr,uid,ids,['state']):
                if rop['state'] not in ('draft'):
                    raise osv.except_osv("KDVN Warning !","Can't delete payment please check status")
        unlink_ids = ids
        return super(kdvn_payment_from_client, self).unlink(cr, uid, unlink_ids, context=context)
    
    def _invoice_no(self, cr, uid, context={}):
        res=''
        cr.execute("Select prefix || substring(date_part('year',current_date)::text from 3 for 2) || '-' ||\
                    lpad((coalesce(max(substring(number from (prefix).length+4 for padding)::int),0)+1)::text,padding,'0')\
                    from\
                    (Select number,(Select prefix from ir_sequence where code='kdvn_payment_from_client' and active=True limit 1) as prefix,\
                    (Select padding from ir_sequence where code='kdvn_payment_from_client' and active=True limit 1) as padding\
                    from kdvn_payment_from_client where number<>'' and number like '____-____') vw\
                    group by prefix,padding")
        if cr.rowcount:
            res=cr.fetchone()[0]
        else:
            cr.execute("Select prefix || substring(date_part('year',current_date)::text from 3 for 2) || '-0001'\
                            from ir_sequence where code='kdvn_claim_payment' and active=True limit 1")
            res=cr.fetchone()[0]
        return res

    def _get_issued_already(self,cr, uid, ids, name, args, context={}):
        res={}
        contract_obj=self.pool.get('kdvn.contract.client')
        for pfc in self.browse(cr,uid,ids):
            res[pfc.id]={'issued_already':0.0,
                         'issued_already_tax':0.0,
                         'issued_already_total':0.0}
#            issued_amount_already = 0.0
#            issued_tax_already = 0.0
#            issued_total_already = 0.0
#            
#            to_rate=pfc.contract_currency_id.rate or 1.0
#            vnd=pfc.contract_currency_id.name=='VND'
            if pfc.number:
                cr.execute("Select \
                                sum(coalesce(amount_e,0)+coalesce(amount_m,0)+coalesce(adv_payment,0)+coalesce(retention,0)+coalesce(others,0)) as issued_already,\
                                sum(kdvn_amount_tax) as issued_already_tax\
                            from \
                                kdvn_payment_from_client\
                            where\
                                number<>'' and number<'%s' and contract_id=%s and state not in ('draft','cancel')" %(pfc.number,pfc.contract_id.id))
                var_temp=cr.dictfetchone()
                if var_temp['issued_already']:
                    var_temp['issued_already_total']=var_temp['issued_already_tax']+var_temp['issued_already']
                    res[pfc.id]=var_temp
#                issued_already_ids=self.search(cr,uid,[('state','!=','draft'),('number','<',pfc.number),('number','<>',''),('contract_id','=',pfc.contract_id.id)],context=None)
#                #raise osv.except_osv("E",issued_already_ids)
#                if issued_already_ids:
#                    for ia in self.browse(cr,uid,issued_already_ids):
#                        #,['project_currency','amount']):
#                        from_rate=ia.contract_currency_id.rate or 0.0
#                        
#                        ia_amount_remain=ia.amount_e + ia.amount_m + ia.adv_payment + ia.retention + ia.others
#                        ia_amount_tax_remain=ia.kdvn_amount_tax
#                        ia_amount_total_remain=ia.kdvn_amount_total
#                        
#                        if vnd and ia.received_ids:
#                            for tmp in ia.received_ids:
#                                ia_amount_total_remain-=tmp.total_amount
#                                ia_amount_tax_remain-=tmp.tax_amount
#                                ia_amount_remain-=tmp.amount
#                                
#                                issued_amount_already+=tmp.actual_amount
#                                issued_tax_already+=tmp.actual_tax_amount
#                                issued_total_already+=tmp.actual_total_amount
#                                
#                        issued_amount_already+=ia_amount_remain*from_rate/to_rate
#                        issued_tax_already+=ia_amount_tax_remain*from_rate/to_rate
#                        issued_total_already+=ia_amount_total_remain*from_rate/to_rate
#            res[pfc.id]={'issued_already':issued_amount_already,
#                         'issued_already_tax':issued_tax_already,
#                         'issued_already_total':issued_total_already}

        return res
    
    def _contract_cost(self,cr, uid, ids, name, args, context={}):
        kcc_obj=self.pool.get('kdvn.contract.client')
        res={}
        for pfc in self.browse(cr,uid,ids):
            if pfc.contract_id:
                contract_id=pfc.contract_id.id
                aaa=kcc_obj.read(cr,uid,[contract_id],['contract_amount_e','contract_amount_m'])[0]
                ctc_cost_list=kcc_obj.read(cr,uid,[contract_id],['contract_amount_vnd','contract_amount_e','contract_amount_m'])
                if pfc.contract_currency_id.name=='VND':
                    contract_amount=ctc_cost_list[0]['contract_amount_vnd']
                else:
                    to_rate=pfc.contract_currency_id.rate
                    from_rate=0.0
                    for pc in pfc.contract_id.contract_currency_ids:
                        if pc.default_curr:
                            from_rate = pc.rate
                    if to_rate:
                        contract_amount=(ctc_cost_list[0]['contract_amount_e']+ctc_cost_list[0]['contract_amount_m'])*from_rate/to_rate
                    else:
                        contract_amount=0
                res[pfc.id]=contract_amount
        for id in ids:
            res[id]=res.get(id,0.0)
        return res

           
    def _kdvn_amount_all(self, cr, uid, ids, name, args, context={}):
        res = {}
        for x in self.browse(cr,uid,ids, context=context):
            res[x.id] =x.amount_e + x.amount_m + x.kdvn_amount_tax + x.adv_payment + x.others + x.retention
        for id in ids:
            res[id] = res.get(id, 0.0)
        return res
                         
    def _exchange_rate(self,cr, uid, ids, name, args, context={}):
        res={}
        for rate in self.browse(cr,uid,ids):
            res[rate.id]=0.0
            if rate.contract_currency_id:
                res[rate.id]=rate.contract_currency_id.rate
        return res
    
    def _exchange_rate_usd(self,cr, uid, ids, name, args, context={}):
        res={}
        for rate in self.browse(cr,uid,ids):
            res[rate.id]=0.0
            if rate.contract_currency_id:
                res[rate.id]=rate.contract_currency_id.rate
        return res
    
    def _kdvn_get_received_all(self, cr, uid, ids, name, args, context={}):
        res = {}
        for kpfc in self.browse(cr,uid,ids):
            tmp_amount = 0.0
            for kdvn_received in kpfc.received_ids:
                tmp_amount = tmp_amount + (kdvn_received.amount or 0.0) + (kdvn_received.tax_amount or 0.0)
            res[kpfc.id] = tmp_amount
        return res
    
    def _get_project_e_m_id(self,cr,uid,ids,name,args,context={}):
        res={}
        for id in ids:
            cr.execute("Select \
                        vwprojectm.id,\
                        project_m_id as job_m_id,\
                        project_e_id as job_e_id\
                    from\
                        (Select\
                            kpfc.id,\
                            project_m_id\
                        from\
                            kdvn_payment_from_client kpfc\
                        left join\
                            kdvn_contract_client kcc on kpfc.contract_id = kcc.id\
                        left join\
                            sale_order so on so.state<>'draft' and kcc.id = so.contract_id and coalesce(project_m_id,0)>0\
                        where \
                           kpfc.id=%s limit 1) vwprojectm\
                    inner join\
                        (Select\
                            kpfc.id,\
                            project_e_id\
                        from\
                            kdvn_payment_from_client kpfc\
                        left join\
                            kdvn_contract_client kcc on kpfc.contract_id = kcc.id\
                        left join\
                            sale_order so on so.state<>'draft' and kcc.id = so.contract_id and coalesce(project_e_id,0)>0\
                        where \
                            kpfc.id=%s limit 1) vwprojecte on vwprojectm.id = vwprojecte.id" % (id,id))
            tmp_dict = cr.dictfetchone()
            res[tmp_dict.pop('id')]=tmp_dict
#            for job_e_id,job_m_id in cr.fetchall():           
#                res[id] = {'job_e_id':job_e_id,'job_m_id':job_m_id}
            #raise osv.except_osv("E",res)
        return res
#    def _get_quotations(self,cr,uid,ids,name,args,context={}):
#        res={}
#        for pfc in self.read(cr,uid,ids,['contract_id']):
#            quos = ''
#            if pfc['contract_id']:
#                ctc_id = pfc['contract_id'][0]
#                cr.execute("Select name from sale_order where state not in ('draft','cancel') and id=%s" % ctc_id)
#                for n in cr.fetchall():
#                    if quos=='':
#                        quos=n
#                    else:
#                        quos=quos+";"+n
#            res[pfc.id] = quos
#        return res
    
    _order = "number" 
    _rec_name = "number"
    _columns = {
            'number':fields.char('Number',size=16,select=1,states={'draft':[('readonly',False)]},readonly=True),
            'date':fields.date('Date',states={'draft':[('readonly',False)]},readonly=True),
            
            'received_ids': fields.one2many('kdvn.received','payment_id','Received Money',readonly=True,states={'open': [('readonly', False)]}),
            'kdvn_red_invoice_ids':fields.many2many('kdvn.red.invoice','payment_from_client_kdvn_red_invoice_rel', 'payment_id', 'red_invoice_id', 'KDVN Red Invoices'),
            'kdvn_payment_vat_invoice_ids':fields.one2many('kdvn.payment.vat.invoice','payment_id','VAT Invoice Amount',states={'open':[('readonly',False)]},readonly=True,required=True),
            
            'contract_id':fields.many2one('kdvn.contract.client','Contract',select=1,states={'draft':[('readonly',False)]},readonly=True,required=True),
            'owner_id':fields.many2one('res.partner','Owner',select=1,states={'draft':[('readonly',False)]},readonly=True),
            'client_id':fields.many2one('res.partner','Client',select=1,states={'draft':[('readonly',False)]},readonly=True),
            'address_id':fields.many2one('res.partner.address','Address',select=1,states={'draft':[('readonly',False)]},readonly=True),
            'invoice_address_id':fields.many2one('res.partner.address','Invoice Address',select=1,states={'draft':[('readonly',False)]},readonly=True),            
            'contract_currency_id':fields.many2one('project.currency',string='Curr.',required=True,states={'draft':[('readonly',False)]},readonly=True),
            'payment_term_line_id':fields.many2one('kdvn.payment.term.line','Payment Term Line'),
            'contract_ref':fields.char('Contract Ref.',size=100),
    
            'attached_progress_sent':fields.boolean('Progress Sent'),
            'attached_progress_received':fields.boolean('Progress Received'),
                
            'state': fields.selection([
                ('draft','Draft'),
                ('open','Waiting for Payment'),
                ('paid','Done'),
                ('cancel','Cancel')
                ],'State', select=True, readonly=True),           
            'exchange_rate':fields.function(_exchange_rate,type='float', digits=(16,2), method=True, string='Ex.Rate'),
            'exchange_rate_usd':fields.function(_exchange_rate_usd,type='float', digits=(16,2), method=True, string='Ref. Ex.Rate(USD)'),
            'adv_payment': fields.float('Adv.Payment', digits=(16,2),states={'draft':[('readonly',False)]},readonly=True),
            'retention': fields.float('Retention', digits=(16,2),states={'draft':[('readonly',False)]},readonly=True),
            'others': fields.float('Others', digits=(16,2),states={'draft':[('readonly',False)]},readonly=True),
            'contract_amount': fields.function(_contract_cost,  digits=(16,2), method=True, string='Contract Amt.',type='float'),
            'issued_already':fields.function(_get_issued_already,string="Issued Amt.",type='float',method=True,digits=(16,2),multi='issued_already'),
            'issued_already_tax':fields.function(_get_issued_already,string="Issued Already Tax",type='float',method=True,digits=(16,2),multi='issued_already'),
            'issued_already_total':fields.function(_get_issued_already,string="Issued Already Total",type='float',method=True,digits=(16,2),multi='issued_already'),
            'kdvn_amount_total':fields.function(_kdvn_amount_all, method=True, digits=(16,2), string='Total',type='float'),
            'received_total':fields.function(_kdvn_get_received_all, method=True, digits=(16,2), string='Received',type='float'),
            #'quotations':fields.function(_get_quotations, method=True, digits=(16,2), string='Received',type='char',size=255),
            
            'job_e_id':fields.function(_get_project_e_m_id,string="Job E",type='many2one',relation='kdvn.project',method=True,multi='job_no'),
            'job_m_id':fields.function(_get_project_e_m_id,string="Job M",type='many2one',relation='kdvn.project',method=True,multi='job_no'),
            
            'amount_e':fields.float('Prog. Amt. E.',states={'draft':[('readonly',False)]},readonly=True),
            'amount_m':fields.float('Prog. Amt. M.',states={'draft':[('readonly',False)]},readonly=True),
            'itemofrequest':fields.char('Item of request',size=256,states={'draft':[('readonly',False)]},readonly=True),
            'description':fields.text('Description',states={'draft':[('readonly',False)]},readonly=True),
            'taxes_percent':fields.selection([(0,'0'),(5,'5'),(10,'10')],"VAT (%)",states={'draft': [('readonly', False)]},select=2,readonly=True),
            'kdvn_amount_tax':fields.float('Taxes',readonly=True,states={'draft': [('readonly', False)]}),     
            'progressno':fields.integer('Progress No')
            }
    _defaults = {  
        'state':lambda *x: 'draft',
        'amount_e':lambda *x: 0.0,
        'amount_m':lambda *x: 0.0,
        'kdvn_amount_tax':lambda *x:0.0,
        'taxes_percent':lambda *x:10,
        'adv_payment':lambda *x:0.0,
        'retention':lambda *x:0.0,
        'others':lambda *x:0.0
        }
    
    def action_cancel(self, cr, uid, ids, *args):
        self.write(cr, uid, ids, {'state':'cancel', 'move_id':False})
        self._log_event(cr, uid, ids,-1.0, 'Cancel Invoice')
        return True

    def action_cancel_draft(self, cr, uid, ids, *args):
        self.write(cr, uid, ids, {'state':'draft'})
        wf_service = netsvc.LocalService("workflow")
        for inv_id in ids:
            wf_service.trg_create(uid, 'kdvn.payment.from.client', inv_id, cr)
        return True
    
    def action_paid_cancel(self, cr, uid, ids, *args):
        self.write(cr,uid,ids,{'state':'cancel'})
        return True
    
    def copy(self, cr, uid, id, default=None, context={}):
        if default is None:
            default = {}
        default = default.copy()
        default.update({'state':'draft'})
        default['number']=''
        if 'date' not in default:
            default['date'] = False
        return super(kdvn_payment_from_client, self).copy(cr, uid, id, default, context)
   
    def _onchange_date(self, cr, uid, ids,oldnumber):
        try:
            oldnumber=oldnumber.strip()
        except:
            oldnumber=oldnumber
        if oldnumber:
            new_number=oldnumber
        else:
            invoice_obj=self.pool.get('kdvn.payment.from.client')
            new_number=invoice_obj._invoice_no(cr,uid)#,{'type':check['type']})
        val={'number':new_number}        
        return {'value':val}
    
    def _onchange_amount_tax(self, cr, uid, ids, per=0.0,amount_e=0.0,amount_m=0.0,kdvn_amount_tax=0.0,adv=0.0,retention=0.0,other=0.0):
        if kdvn_amount_tax:
            amount_tax=kdvn_amount_tax            
        else:
            amount_tax=int(per)*(amount_e+amount_m)/100.0
        amount_total=amount_tax+(amount_e+amount_m)
    
        val={'amount_e':amount_e,'amount_m':amount_m,
             'adv_payment':adv,'retention':retention,'others':other,
             'kdvn_amount_total':amount_total+adv+retention+other,'kdvn_amount_tax':amount_tax}
        result={'value':val}
        return result
    
    def _onchange_partner_id(self, cr, uid, ids, partner_id):
        invoice_addr_id = False
        address_id = False
        if partner_id:
            res = self.pool.get('res.partner').address_get(cr, uid, [partner_id], ['default', 'invoice'])
            invoice_addr_id = res['invoice']
            address_id = False
            if res['default']:
                address_id = res['default'] 
            if not invoice_addr_id and address_id:  
                invoice_addr_id =address_id
                
        result = {'value': {'invoice_address_id': invoice_addr_id,
                            'address_id':address_id}}
        return result
    
    def _onchage_contract_id(self, cr, uid, ids, contract_id,partner_id=False):
        result={}
        if not contract_id:
            result=self._onchange_partner_id(cr,uid,ids,partner_id)
            result['value']['client_id']=partner_id
            result['value']['contract_currency_id']=False
        else:
            owner_id = False
            client_id = False
            address_id = False
            invoice_address_id = False
            contract_currency_id = False
            ctc_ref = False
            ctc_record=self.pool.get('kdvn.contract.client').read(cr,uid,[contract_id],['contract_currency',
                                                                                        'owner_id','client_id',
                                                                                        'address_id','invoice_address_id','contract_ref'])
            if ctc_record:
                ctc_ref = ctc_record[0]['contract_ref']
                if ctc_record[0]['client_id']:
                    client_id=ctc_record[0]['client_id']
                if ctc_record[0]['owner_id']:
                    owner_id=ctc_record[0]['owner_id']
                if ctc_record[0]['address_id']:
                   address_id=ctc_record[0]['address_id']
                if ctc_record[0]['invoice_address_id']:
                    invoice_address_id=ctc_record[0]['invoice_address_id']
                if ctc_record[0]['contract_currency']:
                    contract_currency_id=ctc_record[0]['contract_currency']
                if not invoice_address_id:
                    invoice_address_id = address_id
            result={'value':{'client_id':client_id,'owner_id':owner_id,
                            'address_id': address_id, 'invoice_address_id': invoice_address_id,
                            'contract_currency_id': contract_currency_id,
                            'contract_ref':ctc_ref }}
        return result

kdvn_payment_from_client()

class kdvn_payment_vat_invoice(osv.osv):
    _name = 'kdvn.payment.vat.invoice'
    _description = 'KDVN Payment VAT Invoice'
    _rec_name = 'vat_invoice_id'
    _columns={
              'payment_id':fields.many2one('kdvn.payment.from.client','Client Payment',required=True),
              'vat_invoice_id':fields.many2one('kdvn.red.invoice','VAT No.',required=True),
              'amount':fields.float('Amount'),
              'note':fields.char('Note',size=255)
              }
    _defaults={
               'amount':lambda *a:0.0,
               }
kdvn_payment_vat_invoice()